# -*- coding: utf-8 -*-
"""
    xfree.auth.services.activation
    ~~~~~~~~~~~~~~~~~~~~~
    文件描述：xfree中账户激活的处理程序
    作者：xfree
    邮箱：cy_83k@qq.com
"""

from flask_babelplus import gettext as _

# 从相关模块导入AccountActivator（这里重命名为_AccountActivator）
from...core.auth.activation import AccountActivator as _AccountActivator
from...core.exceptions import ValidationError
from...core.tokens import Token, TokenActions, TokenError
from xfree.utils.email import send_activation_token


class AccountActivator(_AccountActivator):
    """
    xfree的默认账户激活器，通过电子邮件处理激活过程。
    """

    def __init__(self, token_serializer, users):
        """
        初始化方法

        :param token_serializer: 令牌序列化器
        :param users: 用户查询对象（可能是数据库查询相关的对象）
        """
        self.token_serializer = token_serializer
        self.users = users

    def initiate_account_activation(self, email):
        """
        发起账户激活操作

        :param email: 用户的电子邮件地址
        """
        # 根据电子邮件地址查询用户
        user = self.users.query.filter_by(email=email).first()

        if user is None:
            # 如果用户不存在，抛出验证错误
            raise ValidationError("email", _("Entered email doesn't exist"))

        if user.activated:
            # 如果账户已经激活，抛出验证错误
            raise ValidationError("email", _("Account is already activated"))

        # 创建激活令牌
        token = self.token_serializer.dumps(
            Token(user_id=user.id, operation=TokenActions.ACTIVATE_ACCOUNT)
        )

        # 异步发送激活令牌邮件
        send_activation_token.delay(
            token=token, username=user.username, email=user.email
        )

    def activate_account(self, token):
        """
        激活账户操作

        :param token: 激活令牌
        """
        # 反序列化令牌
        token = self.token_serializer.loads(token)
        if token.operation!= TokenActions.ACTIVATE_ACCOUNT:
            # 如果令牌操作不是激活账户，抛出令牌错误
            raise TokenError.invalid()
        user = self.users.query.get(token.user_id)
        if user.activated:
            # 如果账户已经激活，抛出验证错误
            raise ValidationError("activated", _("Account is already activated"))
        # 设置用户账户为已激活状态
        user.activated = True